import React, { Component } from 'react'
import { Card, Icon, Button, Modal, Table, message } from 'antd';
import AddUpdateForm from './add-update-form'
import LinkButton from '../../components/link-button/link-button'
import { reqcategoryList, reqAddCategory, reqUpdateCategory } from '../../api/index'

export default class Category extends Component {
    state = {
        visible: false,
        categoryList: [],
        isLoading: false,
        showStatus: 0 // 0: 不显示  1: 添加分类  2: 修改分类
    };

    //  添加分类的弹框
    showAddModal = () => {
        // 清除上一次停留的值
        this.category = {}
        this.setState({
            showStatus: 1
        })
    };

    // 更新分类的函数
    showUpdateModal = () => {
        this.setState({
            showStatus: 2
        });
    }

    // 弹框OK的函数
    handleOk = e => {
        // console.log(this)
        // 进行表单验证
        this.form.validateFields(async (err, values) => {
            if (!err) {
                // 获取输入框的值
                const { categoryName } = values

                let result
                
                if(this.state.showStatus===1){
                    // 发送请求
                    result = await reqAddCategory(categoryName)
                }else{
                    const categoryId = this.category._id
                    result = await reqUpdateCategory({categoryId,categoryName})
                }

                 // 重置添加输入框的值
                 this.form.resetFields()
                 // 弹框消失
                 this.setState({
                     showStatus: 0,
                 });

                const action = this.state.showStatus === 1 ? '添加' : '修改'
                // 校验是否添加成功
                if (result.status === 0) {
                    message.success(action + '分类成功')
                    // 重新获取分类数据列表
                    this.getcategoryList()
                } else {
                    message.error(action + '分类失败')
                }
               
            }
        });
    };

    // 弹框cancel的函数
    handleCancel = e => {
        this.form.resetFields()
        this.setState({
            showStatus: 0,
        });
    };


    // 发送分类请求列表数据的函数
    getcategoryList = async () => {
        // 发送请求之前现在Loading图标
        this.setState({ isLoading: true })
        // 发异步ajax请求, 获取数据
        const result = await reqcategoryList()
        if (result.status === 0) {
            // 取出分类数组
            const categoryList = result.data
            // 更新状态
            this.setState({
                categoryList,
                isLoading: false
            })
        }
    }

    // 初始化table的列表信息函数
    initTable = () => {
        this.columns = [
            {
                title: '分类名称',
                dataIndex: 'name'
            },
            {
                title: '操作',
                width: '300px',
                //父组件确认当前点击的是哪一个分类
                render: (category) => <LinkButton onClick={() => {
                    // 父组件 render中的category是指点击哪一行就将那一行的数据对象返回
                    this.category = category
                     this.showUpdateModal() 
                    }}>修改分类</LinkButton>
            }
        ];
    }

    /* 
    初始化table的所有列信息的数组
    */
    UNSAFE_componentWillMount() {
        this.initTable()
    }

    componentDidMount() {
        this.getcategoryList()
    }

    render() {
        // 卡片右上角
        const extra = (
            // 这里的点击不希望一上来就执行，可以通过添加函数来实现点击才执行该函数
            <Button type="primary" onClick={() => { this.showAddModal() }}>
                <Icon type="plus" />
                添加
        </Button>
        )

        // 获取this中的category，但是在render中使用，有可能是添加就没有值为undefined，需要给添加定义为一个空对象，修改分类才有值
        const category = this.category || {}

        return (
            <div>
                <Card extra={extra}>
                    <Table
                        columns={this.columns}
                        dataSource={this.state.categoryList}
                        bordered
                        rowKey="_id"
                        pagination={{ defaultPageSize: 5, showQuickJumper: true }}
                        loading={this.state.isLoading}
                    />,
                </Card>

                {/* 弹出的模态框 */}
                <Modal
                    title={this.state.showStatus === 1 ? "添加分类" : "修改分类"}
                    visible={this.state.showStatus !== 0}
                    onOk={this.handleOk}
                    onCancel={this.handleCancel}
                >
                    {/* 表单输入框 */}
                    <AddUpdateForm setForm={form => this.form = form} categoryName={category.name}/>
                </Modal>
            </div>
        )
    }
}


/**添加分类----子组件给父组件传值:
 * 1. 父组件需要定义一个函数，将子组件传递过来的值用form对象接收
 * <AddUpdateForm setForm={ form=>this.form = form }/>  => function(form){return this.form = form}
 * 2. 子组件声明接收哪一个函数
 * import PropTypes from 'prop-types'
 * static propTypes = { // 不加static是给函数，加上static是给对象使用
    setForm: PropTypes.func.isRequired
  }
 * 3. 此时函数接收到函数，需要将自身的form对象传递给父组件（越早传递越好且只需执行一次即可）
 * UNSAFE_componentWillMount(){
        this.props.setForm(this.props.form)
    }
 * 4. 父组件接收到子组件传递的form
 * 5. 从form对象中进行表单验证并获取input的值
 *  5.1 进行表单验证
 *  5.2 验证通过后，得到输入数据
 *  5.3 发送添加分类的请求
 *  5.4 根据响应结果，做不同的处理
 *  this.form.validateFields(async (err, values) => {
      if (!err) {
        // 验证通过后, 得到输入数据
        const { categoryName } = values -------------------------此处的categoryName 是与 getFieldDecorator的一致，如果不一致需要修改
        const  result = await reqAddCategory(categoryName)

        if (result.status===0) {
          // 重新获取分类列表显示（得到最新的列表，需发请求）
          this.getCategorys()
          message.success('添加分类成功')
        } else {
          message.error('添加分类失败')
        }

        this.setState({ showStatus: 0 })
      }
    })
  }
 *
 *
 * 将子组件传递过来的form对象保存到当前组件对象上（需要通过函数传递给父组件）
 */


 /**
  * 修改分类
  * 父组件需要给子组件传送当前选中是哪个分类
  * 父组件确认当前点击的是哪一个分类
  * 
  * 
  * 1. 父组件 render中的category是指点击哪一行就将那一行的数据对象返回（但不是现在使用，需要传给子组件render的时候才使用，需要将数据存到一个公用的地方
  *  {
                title: '操作',
                width: '300px',
                render: (category) => <LinkButton onClick={() => { this.showUpdateModal() }}>修改分类</LinkButton>
     }
  *
  * 2. 父组件将数据存到公用的地方
  * showUpdateModal = () => {
        this.category = category（返回的数据对象）
        this.setState({
            showStatus: 2
        });
    }
  * 
  * 
  * 3. 父组件在render中定义这个category并传递给另外的子组件(但category是添加的时候就取不到值，修改的时候才能获取到值)
  * const category = this.category || {}
  * 
  * 4. 父组件传递给子组件 
  * <AddUpdateForm setForm={form => this.form = form} categoryName={category.name}/>
  * 
  * 5. 子组件声明接收父组件传递的值
  * static propTypes = {
    setForm: PropTypes.func.isRequired,
    categoryName: PropTypes.string (此时不需要isRequired，因为添加分类是没有的)
  }
  * 
  * 
  * 6. 子组件读取并渲染
  * {
        getFieldDecorator('categoryName', {
            initialValue: this.props.categoryName || ''
            rules: [{ required: true, message: '请填写分类信息' }],
        })(<Input placeholder="请填写分类信息" />,)
    }
  * 
  * 7. 父组件修改添加分类和修改分类的表单显示
  * 进行表单验证
    this.form.validateFields(async (err, values) => {
      if (!err) {
        // 验证通过后, 得到输入数据
        const { categoryName } = values

        const {showStatus} = this.state
        let result
        if (showStatus===1) { // 添加
          // 发添加分类的请求
          result = await reqAddCategory(categoryName)
        } else { // 修改
          const categoryId = this.category._id
          result = await reqUpdateCategory({ categoryId, categoryName })
        }

        this.form.resetFields() // 重置输入数据(变成了初始值)
        this.setState({ showStatus: 0 })

        const action = showStatus===1 ? '添加' : '修改'
        // 根据响应结果, 做不同处理
        if (result.status===0) {
          // 重新获取分类列表显示
          this.getCategorys()
          message.success(action + '分类成功')
        } else {
          message.error(action + '分类失败')
        }
      }
    })
  }

  * 
  * 8. 出现的bug：点击修改分类后取消，再点击添加分类，输入框的值为修改分类的默认值
  * 
  * -----> 将前面存储的category值设为空
  *  // Card右上角的结构
    const extra = (
      <Button type="primary" onClick={() => { 
        //   清空上一个category的值
        this.category = {}
        this.setState({ showStatus: 1 })
       }}>
        <Icon type="plus"/>
        添加
      </Button>
    )
  * 
  * 
  * 
  * 
  * 
  */
